#include "worker.h"
#include "thread.h"
#include "logging.h"
#include "common.h"

namespace base
{
	enum
	{
		MSG_HAVEWORK = 0,
	};

	Worker::Worker() : work_thread_(NULL) {}

	Worker::~Worker()
	{
		// We need to already be stopped before being destroyed. We cannot call
		// StopWork() from here because the subclass's data has already been
		// destructed, so OnStop() cannot be called.
		ASSERT(!work_thread_);
	}

	bool Worker::StartWork()
	{
		Thread *me = Thread::Current();
		if (work_thread_)
		{
			if (work_thread_ == me)
				return true; // Already working on this thread, so nothing to do.
			else
			{
				LOG(LS_ERROR) << "Automatically switching threads is not supported";
				ASSERT(false);
				return false;
			}
		}
		work_thread_ = me;
		OnStart();
		return true;
	}

	bool Worker::StopWork()
	{
		if (!work_thread_)
			return true; // Already not working, so nothing to do.
		else if (work_thread_ != Thread::Current())
		{
			LOG(LS_ERROR) << "Stopping from a different thread is not supported";
			ASSERT(false);
			return false;
		}
		OnStop();
		work_thread_->Clear(this, MSG_HAVEWORK);
		work_thread_ = NULL;
		return true;
	}

	void Worker::HaveWork()
	{
		ASSERT(work_thread_ != NULL);
		work_thread_->Post(this, MSG_HAVEWORK);
	}

	void Worker::OnMessage(Message* msg)
	{
		ASSERT(msg->message_id == MSG_HAVEWORK);
		ASSERT(work_thread_ == Thread::Current());
		OnHaveWork();
	}
}